package num12;

import java.util.HashMap;
import java.util.Map;

public class LeecodeLRU {
    /**
     * 链表实体
     * 因为是使用hashmao来完成所以在链表定义的时候要定义对应的key和value
     */
    public class LRUListNode{
        private int value;
        private int key;
        private LRUListNode pre;
        private LRUListNode next;
        LRUListNode(){}
        LRUListNode(int value,int key){
            this.value =value;
            this.key =key;

        }
    }
    /**
     * 参数
     * 1，哈希表
     * 2，虚拟的头节点和尾节点
     * 3，容量
     * 4,当前长度
     * 构造方法
     * get
     * put
     *
     * */

    private Map<Integer,LRUListNode> cache= new HashMap<>();
    private LRUListNode tail,head;
    private int capacity;
    private int size;

    LeecodeLRU(int capacity){
        //size表示当前容量的长度，初始化为0
        this.size = 0;
        this.capacity = capacity;
        head = new LRUListNode();
        tail = new LRUListNode();
        //双向绑定的
        head.next = tail;
        tail.next = head;
    }


    /**
     * get方法
     */
    public int get(int key){
        LRUListNode lruListNode = cache.get(key);
        if (lruListNode == null){
            return -1;
        }else{
            moveToHead(lruListNode);

        }
        return lruListNode.value;
    }
    /**
     * put方法
     */
    public void put(int key,int value){
        LRUListNode lruListNode = cache.get(key);

        if (lruListNode == null){
            LRUListNode lruListNode1 = new LRUListNode(key,value);
            cache.put(key,lruListNode1);
            addToHead(lruListNode1);
            ++size;
            if (size > capacity){
                LRUListNode lruListNode2 = removeTail();
                cache.remove(lruListNode2.key);
                --size;
            }
        }else {
            lruListNode.value = value;
            moveToHead(lruListNode);


        }

    }
    /**
     * 在头节点新增
     */
    public void addToHead(LRUListNode node){
        node.pre = head;
        node.next = head.next;
        head.next.pre = node;
        head.next = node;


    }
    /**
     * moveToHead
     * 移动到头节点
     * 在进行操作的时候使用了当前数据要将当前数据放入头部符合最近最少使用原则
     * 1，首先要删除当前节点
     * 2，其次要当前节点放到头
     */
    public void moveToHead(LRUListNode node){
        removeNode(node);
        addToHead(node);

    }
    /**
     * 删除节点
     */
    public void removeNode(LRUListNode node){

        //当前节点的前驱指向当前的后继
        node.pre.next = node.next;
        //当前节点的后继节点的前驱指向当前节点的前驱
        node.next.pre = node.pre;

    }
    /**
     * removeTail
     * 删除尾节点
     */
    public LRUListNode removeTail(){
        LRUListNode pre = tail.pre;
        removeNode(pre);
        System.out.println("当前要删除的节点为：" + pre);
        return pre;

    }
}
